SPB Git

spb/worthdoing Public

Autonomous investigation agent that discovers, challenges, and ranks things genuinely worth doing — Claude + Firecrawl, Next.js 16, PostgreSQL

TypeScript 91.5% SQL 5.8% CSS 2.2%
2.0 KB · 62 lines typescript
Raw Blame History
1/**2 * WorthDoing.ai3 * Author: Simon-Pierre Boucher4 * Contact: contact@spboucher.ai5 * File: src/app/api/investigations/[id]/route.ts6 * Description: Investigation detail — state snapshot for the live UI (hypotheses, opportunities, budget, phase).7 */8import { NextRequest, NextResponse } from "next/server";9import { z } from "zod";10import { loadState } from "@/lib/agent/state";11import { resumeInvestigation, isRunning } from "@/lib/agent/runner";1213export const dynamic = "force-dynamic";1415export async function GET(_req: NextRequest, ctx: { params: Promise<{ id: string }> }) {16  const { id } = await ctx.params;17  if (!z.string().uuid().safeParse(id).success) {18    return NextResponse.json({ error: "Invalid investigation id." }, { status: 400 });19  }20  try {21    const state = await loadState(id);22    // Self-heal: a "running" investigation with no live engine (server restarted) gets resumed.23    if (state.investigation.status === "running" && !isRunning(id)) {24      void resumeInvestigation(id);25    }26    const inv = state.investigation;27    return NextResponse.json({28      investigation: {29        id: inv.id,30        objective: inv.objective,31        status: inv.status,32        phase: inv.phase,33        stopReason: inv.stopReason,34        outcome: inv.outcome,35        conclusion: inv.conclusion,36        budget: inv.budget,37        budgetUsed: inv.budgetUsed,38        model: inv.model,39        createdAt: inv.createdAt,40        startedAt: inv.startedAt,41        completedAt: inv.completedAt,42        error: inv.error,43      },44      hypotheses: state.hypotheses,45      opportunities: state.opportunities.map((o) => ({46        id: o.id,47        title: o.title,48        summary: o.summary,49        status: o.status,50        worthScore: o.worthScore,51        evidenceConfidence: o.evidenceConfidence,52        hasReport: !!o.reportMd,53      })),54      evidenceCount: state.evidence.length,55      searchCount: state.searches.length,56      sources: state.visitedSources,57    });58  } catch {59    return NextResponse.json({ error: "Investigation not found." }, { status: 404 });60  }61}62